var $ = require("jquery");
//------------------Vector2d-------------------------------//

function Vector2d(x, y) {
    this.x = x;
    this.y = y;
}

// 向量加法
Vector2d.prototype.add = function (vector) {
    return new Vector2d(this.x + vector.x, this.y + vector.y);
}

// 向量减法
Vector2d.prototype.sub = function (vector) {
    return new Vector2d(this.x - vector.x, this.y - vector.y);
}

// 向量点积
Vector2d.prototype.dotProduct = function (vector) {
    return this.x * vector.x + this.y * vector.y;
}

// 向量取反
Vector2d.prototype.negate = function () {
    return new Vector2d(-this.x, -this.y);
}

// 向量模
Vector2d.prototype.length = function () {
    return Math.sqrt(this.x * this.x + this.y * this.y);
}

// 单位向量
Vector2d.prototype.normalize = function () {
    var length = this.length();
    return new Vector2d(this.x / length, this.y / length);
}

// 向量放缩
Vector2d.prototype.scale = function (scale) {
    return new Vector2d(this.x * scale, this.y * scale);
}

// 向量旋转
Vector2d.prototype.rotate = function (angle) {
    var x = this.x;
    var y = this.y;

    var x1 = x * Math.cos(angle) - y * Math.sin(angle);
    var y1 = x * Math.sin(angle) + y * Math.cos(angle);

    return new Vector2d(x1, y1);
}

//------------------utils-------------------------------//

const utils = {
    random: function (min, max) {
        var num = Math.floor(Math.random() * (max - min)) + min;
        return num;
    }
}

//------------------main-------------------------------//

var fontSize = 14;
var canvas;

var width = 0;
var height = 0;

var ctx = null;

var balls = [];

function Ball(x, y, speedX, speedY, color, radius, density, imgurl, text) {
    this.x = x;
    this.y = y;
    this.speedX = speedX;
    this.speedY = speedY;
    this.color = color;
    this.radius = radius;
    this.density = density;
    this.img = new Image();
    this.img.src = imgurl;
    this.text = text
}

Ball.prototype.draw = function () {
    ctx.beginPath();
    // ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
    // ctx.fillStyle = this.color;

    ctx.drawImage(this.img, this.x - this.radius, this.y - this.radius, 25, 15);
    if (this.text) {
        ctx.fillText(this.text, this.x - this.text.length * (fontSize/2), this.y - this.radius);
    }
    ctx.fill();
    //清空弹幕
    let _this = this;
    // setTimeout(function () {
    //     _this.text = "";
    // }, 3000)
}

Ball.prototype.borderCollisionDetect = function () {
    if ((this.x + this.radius) >= width && this.speedX > 0) {
        this.speedX *= -1;
    }

    if ((this.x - this.radius) <= 0 && this.speedX < 0) {
        this.speedX *= -1;
    }

    if ((this.y + this.radius) >= height && this.speedY > 0) {
        this.speedY *= -1;
    }

    if ((this.y - this.radius) <= 0 && this.speedY < 0) {
        this.speedY *= -1;
    }
}

function ballsCollisionDetect(ball1, ball2) {
    //  当前距离
    var dx = ball1.x - ball2.x;
    var dy = ball1.y - ball2.y;
    var distance = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));

    //  预测下一时刻会不会碰撞
    let dx_next = ball1.x + ball1.speedX - ball2.x - ball2.speedX;
    let dy_next = ball1.y + ball1.speedY - ball2.y - ball2.speedY;
    let distance_next = Math.sqrt(Math.pow(dx_next, 2) + Math.pow(dy_next, 2));

    if (distance_next < ball1.radius + ball2.radius && distance_next < distance) {
        return true;
    }
    return false;
}

function collide(ball1, ball2) {
    // 初始速度向量
    let speed_ball1_initial = new Vector2d(ball1.speedX, ball1.speedY);
    let speed_ball2_initial = new Vector2d(ball2.speedX, ball2.speedY);

    // 球心方向单位向量
    let s = new Vector2d(ball2.x - ball1.x, ball2.y - ball1.y);
    s = s.normalize();

    // 垂直球心方向单位向量
    let t = s.rotate(Math.PI / 2);

    // 速度在球心向量上的分速度投影
    let speed_ball1_initial_sc = speed_ball1_initial.dotProduct(s) / s.length();
    let speed_ball2_initial_sc = speed_ball2_initial.dotProduct(s) / s.length();

    // 速度在垂直球心向量上的分速度投影
    let speed_ball1_initial_tc = speed_ball1_initial.dotProduct(t) / t.length();
    let speed_ball2_initial_tc = speed_ball2_initial.dotProduct(t) / t.length();

    // 碰撞后球心方向上的分速度
    let speed_ball1_final_sc = (speed_ball1_initial_sc * (ball1.density * Math.pow(ball1.radius, 3) - ball2.density * Math.pow(ball2.radius, 3)) + 2 * (ball2.density * Math.pow(ball2.radius, 3)) * speed_ball2_initial_sc)
        / (ball1.density * Math.pow(ball1.radius, 3) + ball2.density * Math.pow(ball2.radius, 3));
    let speed_ball2_final_sc = (speed_ball2_initial_sc * (ball2.density * Math.pow(ball2.radius, 3) - ball1.density * Math.pow(ball1.radius, 3)) + 2 * (ball1.density * Math.pow(ball1.radius, 3)) * speed_ball1_initial_sc)
        / (ball1.density * Math.pow(ball1.radius, 3) + ball2.density * Math.pow(ball2.radius, 3));

    // 碰撞后球心方向上的分速度向量
    let speed_ball1_final_s = s.scale(speed_ball1_final_sc);
    let speed_ball2_final_s = s.scale(speed_ball2_final_sc);

    // 碰撞后垂直球心方向上的分速度向量
    let speed_ball1_final_t = t.scale(speed_ball1_initial_tc);
    let speed_ball2_final_t = t.scale(speed_ball2_initial_tc);

    // 结束速度向量
    let speed_ball1_final = speed_ball1_final_s.add(speed_ball1_final_t);
    let speed_ball2_final = speed_ball2_final_s.add(speed_ball2_final_t);

    // 更新速度
    ball1.speedX = speed_ball1_final.x;
    ball1.speedY = speed_ball1_final.y;

    ball2.speedX = speed_ball2_final.x;
    ball2.speedY = speed_ball2_final.y;
}

function update() {
    for (let i = 0; i < balls.length; i++) {
        balls[i].borderCollisionDetect();

        for (let j = i + 1; j < balls.length; j++) {
            if (ballsCollisionDetect(balls[i], balls[j])) {
                collide(balls[i], balls[j]);
            }
        }

        // 更新位置
        balls[i].x += balls[i].speedX;
        balls[i].y += balls[i].speedY;
    }
}

function loop() {
    ctx.clearRect(0, 0, width, height);

    for (let i = 0; i < balls.length; i++) {
        balls[i].draw();
    }

    update();

    requestAnimationFrame(loop);
}

var init = function () {

    canvas = document.querySelector('canvas');

    width = canvas.width;
    height = canvas.height;

    ctx = canvas.getContext('2d');
    ctx.font = fontSize + "px Times New Roman";
    // ctx.fillStyle = "Black";

    loop();

    //定时清空
    window.clear = setInterval(function () {
        clear()
    },60000)
}

function add(dm) {
    var ball = new Ball(
        utils.random(0, width),  // x
        utils.random(0, height), // y
        utils.random(1, 2),     // speedX
        utils.random(1, 2),     // speedY
        'rgb(' + utils.random(0, 255) + ',' + utils.random(0, 255) + ',' + utils.random(0, 255) + ')',
        15,                     // radius
        1,                       // density
        dm.avatar,
        dm.content
    );
    balls.push(ball)

    //定时移除
    setTimeout(function () {
        balls.splice(0, balls.length * 0.1);
    }, 300)
}

var clear = function () {
    console.log('执行清理')
    var marginTop = parseInt($(canvas).css('margin-top'));
    var marginLeft = parseInt($(canvas).css('margin-left'));
    var oHeight = $(canvas).height();
    var oWidth = $(canvas).width();
    var currentRotate = 0;
    var timer = setInterval(() => {
        currentRotate = (currentRotate + 60) % 360;
        $(canvas).height($(canvas).height() / 2)
        $(canvas).width($(canvas).width() / 2)
        $(canvas).css({
            'transform': 'rotate(' + currentRotate + 'deg)',
            'margin-top': parseInt($(canvas).css('margin-top')) + $(canvas).height() / 2,
            'margin-left': parseInt($(canvas).css('margin-left')) + $(canvas).width() / 2
        });
        if ($(canvas).height() <= 1) {
            clearInterval(timer);
            currentRotate = 0;
            balls = [];
            $(canvas).height(oHeight);
            $(canvas).width(oWidth);
            $(canvas).css({
                'transform': 'none',
                'margin-top': marginTop,
                'margin-left': marginLeft
            });
        }
    }, 150)
}

export {
    init,
    add,
    clear
}